package datatypes.list;

import java.util.HashSet;
import java.util.Set;

public class Node<E> {
	private static int nodeCounter = 0;
	
	public Node<E> next = null, previous = null;
	public E element;
	private Set<NodeStakeholder<E>> stakeholders = new HashSet<NodeStakeholder<E>>();
	private int nodeId;
	private boolean removed = false;
	
	Node(E element) {
		nodeId = nodeCounter++;
		this.element = element;
	}
	
	Node(E element, Node<E> previous, Node<E> next) {
		this.element = element;
		this.previous = previous;
		this.next = next;
	}
	
	public void registerAsStakeholder(NodeStakeholder<E> stakeholder) {
		stakeholders.add(stakeholder);
	}
	
	// TODO: Efficiency???
	public void cancelStakeholderRegistration(NodeStakeholder<E> stakeholder) {
		stakeholders.remove(stakeholder);
	}
	
	void remove() {
		setRemoved(true);
//		element = null;
		if (next != null && next.isRemoved()) {
			System.err.println("Referring to a removed node!");
		}
		referStakeholdersToNode(next);
		if (previous != null) {
			previous.next = next;
		}
		
		if (next != null) {
			next.previous = previous;
		}
//		next = null;
//		previous = null;
//		stakeholders = null;
		
	}
	
	public void referStakeholdersToNode(Node<E> newNode) {
//		System.out.println(this + " referring " + stakeholders.size() + " stakeholders to " + node);
		
		for (NodeStakeholder<E> stakeholder : stakeholders) {
			stakeholder.updateNode(newNode);
		}
		stakeholders.clear();
	}
	
	@Override
	public String toString() {
		return "Node " + nodeId + ": " + element;
	}

	private void setRemoved(boolean removed) {
		this.removed = removed;
	}

	public boolean isRemoved() {
		return removed;
	}
}
